﻿using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using BFTest.Classes;
using BFTest.Collision;
using BFTest.Particles;

namespace BFTest.Ammunitions
{
    public enum BulletType
    {
        Rifle,
        Rocket
    }

    abstract class CBullet : ICollideable
    {
        public abstract Vector2 Size { get; set; }
        public abstract float Speed { get; set; }
        public abstract int Damage { get; set; }
        public abstract Color BulletColor { get; set; }
        public abstract BulletType BulletType { get; }

        bool alive;
        public bool Alive { get { return alive; } set { alive = value; } }

        int originID;
        public int OriginID { get { return originID; } private set { originID = value; } }

        string weapon;
        public string Weapon { get { return weapon; } private set { weapon = value; } }

        readonly int id;
        public int ID { get { return id; } }

        public float BoundingRadius { get { return 2; } }

        Vector2 position;
        public Vector2 Position 
        { 
            get { return position; } 
            private set
            {
                position = value;
                UpdateBoundingBox();
            }
        }

        Vector2 direction;
        public Vector2 Direction { get { return direction; } set { direction = value; } }

        Vector2 velocity;
        public Vector2 Velocity { get { return velocity; } set { velocity = value; } }

        Rectangle boundingBox;
        public Rectangle BoundingBox { get { return boundingBox; } private set { boundingBox = value; } }

        public CBullet(int originID, Vector2 position, Vector2 direction, int ID, string weapon)
        {
            OriginID = originID;
            Position = position;
            Direction = Vector2.Normalize(direction);
            this.id = ID;
            Weapon = weapon;
            Velocity = Speed * Direction;
            Alive = true;
        }

        protected virtual void Initialize()
        {
        }

        public virtual void Draw(SpriteBatch spriteBatch)
        {
        }

        public virtual void Update(GameTime gameTime)
        {
            Position += (Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds);

            // Remove bullets that have left the battlefield
            if (!BoundingBox.Intersects(BFTestGame.Battlefield.PlayAreaSize))
                Alive = false;

            // Check for collision with a soldier
            DiscreetTestForCollisions();
        }

        // TODO: Find a way to get the current game time without having to pass it through on every hit check
        private void DiscreetTestForCollisions()
        {
            int bloodCount = 10;
            float bloodRange = MathHelper.ToRadians(90);

            foreach (CUnit unit in BFTestGame.Battlefield.AllUnits)
            {
                // Don't hit the originating soldier since bullets begin at their position right now. 
                if (unit.ID != OriginID && BoundingBox.Intersects(unit.AABoundingBox))
                {
                    for (int x = 0; x < bloodCount; x++)
                    {
                        float offset = (float)((BFTestGame.Battlefield.Rand.NextDouble() * bloodRange) - (bloodRange / 2));
                        BFTestGame.Particles.Add(new CParticleBlood(unit.Position, (Velocity / BFTestGame.Battlefield.Rand.Next(5)).RotateVector(offset), TimeSpan.FromSeconds(0.25f), true));
                    }

                    if(unit.Status != UnitStatus.Dead)
                        unit.Messages.Add("I was hit by " + BFTestGame.Battlefield.GetUnitByID(OriginID).SoldierName + "'s " + Weapon + ".");

                    if (unit.ModifyHealth(-Damage) == true)
                    {
                        // Last hit killed this unit
                        unit.Messages.Add("I was killed by " + BFTestGame.Battlefield.GetUnitByID(OriginID).SoldierName + "'s " + Weapon + ".");
                        BFTestGame.Battlefield.MessageList.Add(unit.SoldierName + " was killed by " + BFTestGame.Battlefield.GetUnitByID(OriginID).SoldierName + ".");
                    }

                    Alive = false;
                }
            }
        }

        protected void UpdateBoundingBox()
        {
            BoundingBox = new Rectangle(
                (int)(Position.X - (Size.X / 2)),
                (int)(Position.Y - (Size.Y / 2)),
                (int)Size.X, (int)Size.Y);
        }

        public void SetPosition(CollisionManagerGC manager, Vector2 position)
        {
            if (manager != null)
                Position = position;
            throw new ArgumentNullException("manager", "Must pass Valid CollisionManager to SetPosition Method");
        }
    }
}
